import { ColumnGroupType, ColumnType } from "antd/es/table"
import Decimal from "decimal.js"
import md5 from "js-md5"

import { Toast } from "@/components/messages"
import { DICT_DEFAULT_CONFIG } from "@/constants/dict"
import dayjs, { Dayjs } from "@/utils/dayjs"
import { REG_ONLY_CHINESE_NO_OTHERS } from "@/utils/validate"

import { cardsNameMap } from "./const"
import { isString } from "./is"
const DEFAULT_FORMAT: string = "YYYY-MM-DD"

const storage = {
	get: (key: string) => localStorage.getItem(key)
}

export const formatFunc = (val: dayjs.ConfigType, format?: string) => {
	if (!val) {
		return "-"
	}

	return dayjs.tz(val).format(format || DEFAULT_FORMAT)
}

/**
 * 获取当天时间
 */
export const getToday = (format?: string) => {
	const date = dayjs.tz().endOf("day")
	return formatFunc(+date, format)
}

/**
 * @description 清除localStorage
 * @param {String} key Storage名称
 * @return void
 */
export const localRemove = (key: string) => {
	window.localStorage.removeItem(key)
}

/**
 * @description 清除所有localStorage
 * @return void
 */
export const localClear = () => {
	window.localStorage.clear()
}

/**
 * @description 获取浏览器默认语言
 * @return string
 */
export const getBrowserLang = () => {
	let browserLang = navigator.language ? navigator.language : navigator.browserLanguage
	let defaultBrowserLang = ""
	if (browserLang.toLowerCase() === "cn" || browserLang.toLowerCase() === "zh" || browserLang.toLowerCase() === "zh-cn") {
		defaultBrowserLang = "zh_CN"
	} else {
		defaultBrowserLang = "en_US"
	}
	return defaultBrowserLang
}

export const toFixed =
	(digits: number, isSubZero = true) =>
	(volume: number) => {
		let str = volume.toString()
		let strIndex = str.indexOf(".")
		if (strIndex === -1) {
			str = `${str}.${"0".repeat(8)}`
		} else {
			str = `${str}${"0".repeat(8)}`
		}
		strIndex = str.indexOf(".")
		str = str.substring(0, strIndex + digits + 1)
		return !digits || isSubZero ? Number(str) : str
	}

export const md5Password = (password: string): string => {
	return md5(password).toUpperCase()
}

export function formatTime(time: any, tformat = "YYYY-MM-DD HH:mm:ss") {
	if (time === null || time === undefined || time === "") {
		return "-"
	}
	let timeObject
	if (/^[0-9]{1,}$/.test(time)) {
		if (String(time).length >= 13) {
			timeObject = dayjs.tz(Number(time))
		} else {
			timeObject = dayjs.tz(dayjs.unix(Number(time)))
		}
	} else {
		timeObject = dayjs.tz(time)
	}

	if (timeObject.isValid()) {
		return timeObject.format(tformat)
	} else {
		return "-"
	}
}

export const formatLessThanTenTime = (num: number) => {
	if (num < 10) {
		return "0" + num
	} else {
		return num
	}
}

export const sliceStr = (str: string, start: number, end: number) => {
	if (!isString(str)) {
		str = String(str)
	}
	if (!str) {
		return str
	} else if (str.length > end - start) {
		return `${str.slice(start, end)}...`
	} else {
		return str
	}
}

// 数字+字母
export const onlyNumAlp = (val: string) => {
	if (!val) {
		return ""
	}
	return val.replace(/[^A-Za-z0-9]/g, "")
}

// type为text 只能输入数字
export const onlyTextNumber = (val: string) => {
	if (!val) {
		return ""
	}
	return val.replace(/\D/g, "")
}
// type为chinese 只能输入中文
export const onlyChinese = (val: string) => {
	if (!val) {
		return ""
	}
	return val.replace(REG_ONLY_CHINESE_NO_OTHERS, "")
}

export const onlyNum = (val: string, precision = 2) => {
	let targetValue = val

	targetValue = targetValue.replace(/[^\d.]/g, "")
	targetValue = targetValue.replace(/^\./g, "")
	targetValue = targetValue.replace(".", "$#$").replace(/\./g, "").replace("$#$", ".")

	if (precision && Number(precision) > 0) {
		// 限制n位
		const d = new Array(Number(precision)).fill(`\\d`).join("")
		const reg = new RegExp(`^(\\-)*(\\d+)\\.(${d}).*$`, "ig")
		targetValue = targetValue.replace(reg, "$1$2.$3")
	}

	if (targetValue && !targetValue.includes(".")) {
		targetValue = Number(targetValue).toString() // 去掉开头多个0
	}

	if (!precision) {
		targetValue = targetValue.replace(".", "")
	}
	return targetValue
}

export const replaceUrlArg = (url: string, arg: string, argVal: string) => {
	const urlObj = new URL(url)
	urlObj.searchParams.set(arg, argVal)
	return urlObj.href
}

export const delUrlArg = (url: string, arg: string) => {
	const urlObj = new URL(url)
	urlObj.searchParams.delete(arg)
	return urlObj.href
}

export const getDownLoadUrl = (pcUrl: string, invitationCode: string) => {
	if (!pcUrl) return ""
	let iCode = "i_code"
	if (invitationCode) {
		pcUrl = `${pcUrl}?${iCode}=${invitationCode}`
	}
	return pcUrl
}

export const getURLParams = () => {
	const url = window.location.href
	// 通过 ? 分割获取后面的参数字符串
	const urlStr = url.split("?")[1]
	if (!urlStr) return {}
	// 创建空对象存储参数
	const obj: {
		[key: string]: string
	} = {}
	// 再通过 & 将每一个参数单独分割出来
	let paramsArr = urlStr.split("&")
	for (let i = 0, len = paramsArr.length; i < len; i++) {
		// 再通过 = 将每一个参数分割为 key:value 的形式
		let arr = paramsArr[i].split("=")
		obj[arr[0]] = arr[1]
	}
	return obj
}

export const ToCDB = (str: string) => {
	let tmp = ""
	for (let i = 0; i < str.length; i++) {
		if (str.charCodeAt(i) == 12288) {
			tmp += String.fromCharCode(str.charCodeAt(i) - 12256)
			continue
		}
		if (str.charCodeAt(i) > 65280 && str.charCodeAt(i) < 65375) {
			tmp += String.fromCharCode(str.charCodeAt(i) - 65248)
		} else {
			tmp += String.fromCharCode(str.charCodeAt(i))
		}
	}
	return tmp
}

export const getLength = (str: string, maxLen = 12, disZhCn = true) => {
	let realLength: number = 0,
		len = str.length,
		charCode = -1,
		newStr = ""

	for (let i = 0; i < len; i++) {
		charCode = str.charCodeAt(i)
		if (charCode >= 0 && charCode <= 128) {
			realLength += 1
		} else {
			realLength += disZhCn ? 2 : 1
		}
		if (maxLen && realLength <= maxLen) {
			newStr += str[i]
		}
	}
	return {
		realLength,
		newStr
	}
}

export const handleJumpOpen = (url: string) => {
	if (!url) return
	if (url.substring(0, 7).toLowerCase() == "http://" || url.substring(0, 8).toLowerCase() == "https://") {
		window.open(url)
	} else {
		url = "http://" + url
		window.open(url)
	}
}

// 脱敏
export const desensitization = (str: string, beginLen = 4, endLen = -4) => {
	if (!str) {
		return ""
	}

	let tempStr = ""

	// const len = str.length;

	const firstStr = str.substr(0, beginLen)

	const lastStr = str.substr(endLen)

	// const middleStr = str.substring(beginLen, len - Math.abs(endLen)).replace(/[\s\S]/gi, "*");
	const middleStr = " **** "

	tempStr = firstStr + middleStr + lastStr

	return tempStr
}

// 脱敏 电话号码，前三后四
export const desensitizationPhone = (str: string) => {
	if (!str) {
		return "-"
	}

	const strArr = str.split("-")
	const phone = strArr[1]

	const dPhone = phone.slice(0, 3) + " **** " + phone.slice(-4)

	let isAddUnit = true

	if (str.startsWith("+")) {
		isAddUnit = false
	}
	return `${isAddUnit ? "+" : ""}${strArr[0]} ${dPhone}`
}

// 数组去重
export const uniqueArray = (_arr: Array<any>, key: string) => {
	if (_arr?.length === 0) return []
	const obj: { [key: string]: boolean } = {}
	return _arr.reduce((item: any, next: any) => {
		if (!obj[next[key]]) {
			item.push(next)
			obj[next.key] = true
		}
		return item
	}, [])
}

/*网页是否能访问，能则返回时间*/
export function isAccessibleUrl(url: string) {
	return new Promise(resolve => {
		const xhr = new XMLHttpRequest()
		xhr.timeout = 15 * 1000
		const starTime = new Date().getTime()

		xhr.open("HEAD", url)
		xhr.onreadystatechange = function () {
			if (xhr.readyState === XMLHttpRequest.DONE) {
				if (xhr.status === 200) {
					const endTime = new Date().getTime()
					const downTime = endTime - starTime
					resolve({ status: true, url, time: downTime })
				} else {
					// 该网页不通
					resolve({ status: false, url })
				}
			}
		}
		xhr.onerror = function () {
			resolve({ status: false, url }) // 该网页不通
		}
		xhr.ontimeout = function () {
			resolve({ status: false, url }) // 网络超时，默认网页不通
		}
		xhr.send()
	})
}

// 处理精度丢失数字
export function precisionNumber(num: number) {
	return parseFloat(num.toPrecision(12))
}

export const convertToChinaNum = (num: any) => {
	let arr1 = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"]
	let arr2 = ["", "十", "百", "千", "万", "十", "百", "千", "亿", "十", "百", "千", "万", "十", "百", "千", "亿"] //可继续追加更高位转换值
	if (!num || isNaN(num)) {
		return "零"
	}
	let english = num.toString().split("")
	let result = ""
	for (let i = 0; i < english.length; i++) {
		let des_i = english.length - 1 - i //倒序排列设值
		result = arr2[i] + result
		let arr1_index = english[des_i]
		result = arr1[arr1_index] + result
	}
	//将【零千、零百】换成【零】 【十零】换成【十】
	result = result.replace(/零(千|百|十)/g, "零").replace(/十零/g, "十")
	//合并中间多个零为一个零
	result = result.replace(/零+/g, "零")
	//将【零亿】换成【亿】【零万】换成【万】
	result = result.replace(/零亿/g, "亿").replace(/零万/g, "万")
	//将【亿万】换成【亿】
	result = result.replace(/亿万/g, "亿")
	//移除末尾的零
	result = result.replace(/零+$/, "")
	//将【零一十】换成【零十】
	//result = result.replace(/零一十/g, '零十');//貌似正规读法是零一十
	//将【一十】换成【十】
	result = result.replace(/^一十/g, "十")
	return result
}

/**判断当前设备类型*/
export const judgeCurrentDevice = () => {
	return window.screen.width >= 1025 ? "PC" : "Mobile"
}

export const flatObj = (obj1: Record<string, any>, pre = "", temp: Record<string, string> = {}) => {
	Object.keys(obj1).forEach(key => {
		if (typeof obj1[key] === "string") {
			temp[pre + key] = obj1[key].charAt(0).toUpperCase() + obj1[key].slice(1)
		} else flatObj(obj1[key], pre + key + ".", temp)
	})
	// return temp
}

export const formatHyphen = (text: string | number) => {
	if (!text) return text
	return String(text).replace(/_/g, "-")
}

export const handleNumber = (sign?: string, num?: string, digit = 2, flag = true, plusSign = false) => {
	if (typeof num === "number" || typeof num === "string") {
		let currencySymbol = storage.get("currencySymbol")
		num = parseFloat(num) ? parseFloat(num).toString() : "0"

		if (sign === "¥") {
			currencySymbol = sign
		}

		if (sign !== "") {
			switch (currencySymbol) {
				case "¥":
				case "$":
				case "฿":
					digit = 2
					break
				case "₫":
					digit = 0
					break
				default:
					digit = 2
					currencySymbol = "$"
			}

			const data = new Decimal(new Decimal(num).toFixed(digit, Decimal.ROUND_DOWN)).toNumber()

			const newData = data.toLocaleString("en-us", {
				minimumFractionDigits: data === 0 ? 0 : digit,
				useGrouping: flag
			})

			const regexp = /(?:\.0*|(\.\d+?)0+)$/

			if (newData.indexOf("-") !== -1) {
				const str1 = newData.replace(/-/g, "")
				return `${data === 0 ? "" : "-"}${currencySymbol}${str1.replace(regexp, "$1")}`
			} else {
				return `${plusSign && data !== 0 ? "+" : ""}${currencySymbol}${newData.replace(regexp, "$1")}`
			}
		} else {
			const data = new Decimal(new Decimal(num).toFixed(digit, Decimal.ROUND_DOWN)).toNumber()

			const newData = data.toLocaleString("en-us", {
				minimumFractionDigits: data === 0 ? 0 : digit,
				useGrouping: flag
			})

			return newData
		}
	} else {
		if (sign !== "") {
			return "$0"
		} else {
			return "-"
		}
	}
}

export const handleNumberColor = (val: number) => {
	let color = ""
	if (val > 0) {
		color = "#13c2c2" // 绿色
	}
	if (val < 0) {
		color = "#D9001B" // 红色
	}
	return color
}

export const handleCurrency = (flag: any) => {
	const currencySymbol = storage.get("currencySymbol")
	if (flag) {
		return currencySymbol
	} else {
		return ""
	}
}

export const getCardsName = (cardsNumStr: string) => {
	let cardsName = ""
	if (cardsNumStr) {
		const cardsNumReplaceStr = cardsNumStr.replace(/[[\]]/g, "")
		if (cardsNumReplaceStr) {
			const cardsNumArr = cardsNumReplaceStr.split(",")
			const cardsNameArr: string[] = []
			cardsNumArr.forEach(item => {
				const cardName = cardsNameMap.get(parseInt(item))
				if (cardName) {
					cardsNameArr.push(cardName)
				}
			})
			cardsName = cardsNameArr.join("，")
		}
	}
	return cardsName
}

export const getPublicCardsName = (publicCard: any) => {
	const cardsName = getCardsName(publicCard)
	return cardsName ? cardsName : "-"
}

export const parseVirtualCurrency = (str: string) => {
	if (!str) {
		return "-"
	} else {
		const replaceStr = "****"
		const firstStr = str.substring(0, 4)
		const secondStr = str.slice(-4)
		str = `${firstStr}${replaceStr}${secondStr}`
		return str
	}
}
// 商户key显示过滤
export const parseMerchantKeyCard = (str: string) => {
	if (!str) {
		return "-"
	} else {
		const arr: any = []
		const nameStr = str.substring(2, str.length - 2)
		for (const item in [...nameStr]) {
			arr[item] = [...nameStr][item].replace([...nameStr][item], "*")
		}
		const replaceStr = arr.join("")
		str = str.replace(nameStr, replaceStr)
		return str
	}
}

export const getTypeName = (code: number, typeArr: any[]) => {
	if (!code && Number(code) !== 0) return "-"
	if (Array.isArray(typeArr)) {
		return (
			typeArr.find(item => (!isNaN(Number(code)) ? Number(item.code) === Number(code) : item.code === code))?.description || "-"
		)
	} else {
		return "-"
	}
}

export const getLabelByValue = (value: string | number, arr: { value: string | number; label: string }[]) => {
	const item = arr.find(item => item.value === value)
	return item ? item.label : "-"
}

export const getDescriptionByCode = (code: string | number, arr: { code: string | number; description: string }[]) => {
	const item = arr.find(item => item.code === code)
	return item ? item.description : "-"
}
export const formatCurrency = (amount: string | number, moneyType: string) => {
	let _amount = amount ? Number(amount) : 0
	if (moneyType == "USDT") {
		moneyType = "USD"
	} else {
		moneyType = "USD"
	}
	const formatAmount = _amount.toLocaleString("en-US", {
		style: "currency",
		currency: moneyType,
		maximumFractionDigits: 0
	})
	return formatAmount
}

export const calculateDateDifference = (date1: string, date2: string) => {
	const dateArray = []

	// 将日期字符串转换为Date对象，注意截取年、月、日的部分
	const year1 = parseInt(date1.substring(0, 4), 10)
	const month1 = parseInt(date1.substring(4, 6), 10) - 1 // 月份从0开始，所以要减1
	const day1 = parseInt(date1.substring(6, 8), 10)

	const year2 = parseInt(date2.substring(0, 4), 10)
	const month2 = parseInt(date2.substring(4, 6), 10) - 1
	const day2 = parseInt(date2.substring(6, 8), 10)

	const d1 = new Date(year1, month1, day1)
	const d2 = new Date(year2, month2, day2)

	// 循环生成日期数组
	while (d1 <= d2) {
		const formattedDate = d1.getFullYear() * 10000 + (d1.getMonth() + 1) * 100 + d1.getDate()
		dateArray.push(formattedDate)
		d1.setDate(d1.getDate() + 1)
	}
	dateArray.reverse()
	return dateArray
}

type ObjectWithIndex = {
	[key: string]: any
}

export const handleAmount = (obj: ObjectWithIndex, flag: number, minField: string, maxField: string, msg: string) => {
	if (obj[minField as keyof typeof obj] && obj[maxField as keyof typeof obj]) {
		switch (flag) {
			case 1:
				if (Number(obj[minField as keyof typeof obj]) > Number(obj[maxField as keyof typeof obj])) {
					obj[minField] = undefined
					Toast.warning(msg)
				}
				break
			case 2:
				if (Number(obj[maxField as keyof typeof obj]) < Number(obj[minField as keyof typeof obj])) {
					obj[maxField] = undefined
					Toast.warning(msg)
				}
				break
		}
	}
}

export const getRebateCycle = (date1: string, date2: string) => {
	date1 = date1 && dayjs(String(date1)).format("YYYY-MM-DD")
	date2 = date2 && dayjs(String(date2)).format("YYYY-MM-DD")

	if (date1 === date2) {
		return date1 || "-"
	} else {
		return date1 && date2 ? date1 + " - " + date2 : "-"
	}
}

export const timeTurner = (value: number) => {
	let time = value
	const day = Math.floor(time / 86400) // 整数部分代表的是天；一天有24*60*60=86400秒 ；

	time = time % 86400 // 余数代表剩下的秒数；

	const hour = Math.floor(time / 3600) // 整数部分代表小时；

	time %= 3600 // 余数代表 剩下的秒数；

	const minute = Math.floor(time / 60)

	time %= 60

	const str = `${day > 0 ? day + "d" : ""}${hour > 0 || day ? hour + "h" : ""}${minute > 0 || hour ? minute + "m" : ""}${time}s`
	return str
}

export const mappingBusinessModelFilter = (key: string) => {
	return DICT_DEFAULT_CONFIG.businessModels.find(item => item?.value == key)?.label || "-"
}

// export const handlePercentage = (num: number, flag = true) => {
// 	if (!num) {
// 		return "0%"
// 	}
// 	const data = new Decimal(new Decimal(num).toFixed(3, Decimal.ROUND_DOWN)).toNumber()
// 	const str = data.toLocaleString("en-us", {
// 		minimumFractionDigits: data === 0 ? 0 : 3,
// 		useGrouping: flag
// 	})
// 	const regexp = /(?:\.0*|(\.\d+?)0+)$/
// 	if (str || str === "0") {
// 		return `${str.replace(regexp, "$1")}%`
// 	} else {
// 		return `-`
// 	}
// }

export const getFormateDate = (date: string, type = "ymd") => {
	let format = "YYYY-MM-DD"
	if (type === "ym") {
		format = "YYYY-MM"
	}
	return date ? dayjs(String(date)).format(format) : "-"
}
export const handlePercentage = (num: number, flag: boolean = true): string => {
	if (!num) {
		return "0%"
	}

	const data = new Decimal(new Decimal(num).toFixed(3, Decimal.ROUND_DOWN)).toNumber()

	const str = data.toLocaleString("en-US", {
		minimumFractionDigits: data === 0 ? 0 : 3,
		useGrouping: flag
	})

	const regexp = /(?:\.0*|(\.\d+?)0+)$/

	if (str !== null && str !== undefined) {
		return `${str.replace(regexp, "$1")}%`
	} else {
		return "-"
	}
}

/**
 * Maps over the columns in a record and applies a new format function to each column title.
 * Make sure that the key will have prefix and separator (_)
 * Example of input: {
 *  orderList_id: {
        title: label.id;
        width: 120;
    };
    orderList_orderNo: {
        title: label.orderNo;
        width: 200;
    };
 * }
 * Example of return: {
 *  id: {
			title: newFormat('label.id');
			dataIndex: id,
			align: 'center',    
			width: 120;
    };
    orderNo: {
			title: newFormat('label.orderNo');
			dataIndex: orderNo,
			align: 'center',
			width: 200
    };
 * }
 * @param func - A function that returns a record of columns.
 * @param newFormat - A function that takes a string as an argument and returns a new formatted string.
 * @returns A record of columns with the updated titles and text alignment, also format empty value into '-'.
 */

export const mapColumns = (
	func: () => Record<string, ColumnGroupType<any> | ColumnType<any>>,
	newFormat: (arg: string) => string
): Record<string, ColumnGroupType<any> | ColumnType<any>> => {
	const columns = func()
	return Object.fromEntries(
		Object.entries(columns).map(([key, value]) => {
			let dataIndex = key
			if (key.includes("_")) dataIndex = key.split("_")[1]
			return [
				key,
				{
					...value,
					title: typeof value.title === "string" ? newFormat(value.title) : value.title,
					align: "center",
					dataIndex,
					render: (val, record, index) => (value.render ? value.render(val, record, index) : val || "-")
				}
			]
		})
	)
}

export const getNumberValue = (val: any) => {
	return val || val === 0 ? val : "-"
}

export const generatePrefixVariables = (columns: any, columnKeyPrefix: string) => {
	const prefixVariables: any = {}

	columns.forEach((column: any) => {
		const prefixName = `${columnKeyPrefix}${column.dataIndex}`

		prefixVariables[prefixName] = column
	})

	return prefixVariables
}

export const getWidth = (locale: string, value: any, scale: number = 1.25) => {
	if (locale === "zh_CN") {
		return value
	}

	if (typeof value !== "object" && value) {
		const numberMatch = String(value).match(/\d+/)
		const number = numberMatch ? parseFloat(numberMatch[0]) : null

		if (number !== null) {
			return typeof value === "number"
				? parseFloat(String(value).replace(/\d+/, (number * scale).toString()))
				: String(value).replace(/\d+/, (number * scale).toString())
		}
	}

	return undefined
}

export const rangeToday = (): Dayjs => dayjs().startOf("day")

export const rangeTomorrow = (): Dayjs => dayjs().startOf("day").add(1, "d")

export const rangeYesterday = (): Dayjs => dayjs().startOf("day").subtract(1, "d")

export const rangeBeforeYesterday = (): Dayjs => dayjs().startOf("day").subtract(2, "d")

export const handleTotalNumber = (currencySymbol: string, sign: any, num: any, digit = 0, flag = true, plusSign = false) => {
	if (typeof num === "number" || typeof num === "string") {
		switch (currencySymbol) {
			case "￥":
				digit = 2
				break
			case "฿":
				digit = 2
				break
			case "₫":
				digit = 0
				break
			case "$":
				digit = 2
				break
			default:
				digit = 2
		}
		num = parseFloat(num + "") ? num : 0
		if (sign === "10k") num /= 10000
		const data = new Decimal(new Decimal(num).toFixed(digit, Decimal.ROUND_DOWN)).toNumber()
		const str = data.toLocaleString("en-us", {
			minimumFractionDigits: data === 0 ? 0 : digit,
			useGrouping: flag
		})
		const regexp = /(?:\.0*|(\.\d+?)0+)$/

		if (str.indexOf("-") !== -1) {
			// eslint-disable-next-line no-useless-escape
			const str1 = str.replace(/\-/g, "")
			return `${data === 0 ? "" : "-"}${currencySymbol}${str1.replace(regexp, "$1")}`
		} else {
			return `${plusSign && data !== 0 ? "+" : ""}${currencySymbol}${str.replace(regexp, "$1")}`
		}
	} else if (num === null) {
		return "-"
	} else {
		return `${currencySymbol}0`
	}
}

export const defaultOutsType = "反超Outs"

export const outsTypeMap = new Map([
	[1, "反超Outs"],
	[2, "平分Outs"]
])
export const getOutsTypeName = (val: any) => {
	return outsTypeMap.get(val) || defaultOutsType
}
export const statusMap = {
	0: "未开始",
	1: "进行中",
	2: "已结束"
}
